/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2006
* Sleepycat Software. All rights reserved.
*
* $Id: CleanerFileReader.java,v 1.1 2006/05/06 09:00:04 ckaestne Exp $
*/
package com.sleepycat.je.log;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.log.entry.INLogEntry;
import com.sleepycat.je.log.entry.LNLogEntry;
import com.sleepycat.je.log.entry.LogEntry;
import com.sleepycat.je.tree.IN;
import com.sleepycat.je.tree.LN;
import com.sleepycat.je.utilint.DbLsn;
/**
* CleanerFileReader scans log files for INs and LNs.
*/
public class CleanerFileReader extends FileReader {
private static final byte IS_IN = 0;
private static final byte IS_LN = 1;
private static final byte IS_ROOT = 2;
private Map targetEntryMap;
private LogEntry targetLogEntry;
private byte targetCategory;
/**
* Create this reader to start at a given LSN.
* @param env The relevant EnvironmentImpl.
* @param readBufferSize buffer size in bytes for reading in log.
* @param startLsn where to start in the log, or null for the beginning.
* @param fileNum single file number.
*/
public CleanerFileReader(EnvironmentImpl env,
int readBufferSize,
long startLsn,
Long fileNum)
throws IOException, DatabaseException {
super(env,
readBufferSize,
true, // forward
startLsn,
fileNum, // single file number
DbLsn.NULL_LSN, // endOfFileLsn
DbLsn.NULL_LSN); // finishLsn
targetEntryMap = new HashMap();
addTargetType(IS_LN, LogEntryType.LOG_LN_TRANSACTIONAL);
addTargetType(IS_LN, LogEntryType.LOG_LN);
addTargetType(IS_LN, LogEntryType.LOG_NAMELN_TRANSACTIONAL);
addTargetType(IS_LN, LogEntryType.LOG_NAMELN);
addTargetType(IS_LN, LogEntryType.LOG_MAPLN_TRANSACTIONAL);
addTargetType(IS_LN, LogEntryType.LOG_MAPLN);
addTargetType(IS_LN, LogEntryType.LOG_DEL_DUPLN_TRANSACTIONAL);
addTargetType(IS_LN, LogEntryType.LOG_DEL_DUPLN);
addTargetType(IS_LN, LogEntryType.LOG_DUPCOUNTLN_TRANSACTIONAL);
addTargetType(IS_LN, LogEntryType.LOG_DUPCOUNTLN);
addTargetType(IS_LN, LogEntryType.LOG_FILESUMMARYLN);
addTargetType(IS_IN, LogEntryType.LOG_IN);
addTargetType(IS_IN, LogEntryType.LOG_BIN);
addTargetType(IS_IN, LogEntryType.LOG_DIN);
addTargetType(IS_IN, LogEntryType.LOG_DBIN);
addTargetType(IS_ROOT, LogEntryType.LOG_ROOT);
}
private void addTargetType(byte category, LogEntryType entryType)
throws DatabaseException {
targetEntryMap.put(entryType,
new EntryInfo(entryType.getNewLogEntry(),
category));
}
/**
* Helper for determining the starting position and opening
* up a file at the desired location.
*/
protected void initStartingPosition(long endOfFileLsn,
Long fileNum)
throws IOException, DatabaseException {
eof = false;
/*
* Start off at the startLsn. If that's null, start at the
* beginning of the log. If there are no log files, set
* eof.
*/
readBufferFileNum = fileNum.longValue();
readBufferFileEnd = 0;
/*
* After we read the first entry, the currentEntry will
* point here.
*/
nextEntryOffset = readBufferFileEnd;
}
/**
* @return true if this is a type we're interested in.
*/
protected boolean isTargetEntry(byte entryTypeNum,
byte entryTypeVersion) {
LogEntryType fromLogType = new LogEntryType(entryTypeNum,
entryTypeVersion);
/* Is it a target entry? */
EntryInfo info = (EntryInfo) targetEntryMap.get(fromLogType);
if (info == null) {
return false;
} else {
targetCategory = info.targetCategory;
targetLogEntry = info.targetLogEntry;
return true;
}
}
/**
* This reader instantiates an LN and key for every LN entry.
*/
protected boolean processEntry(ByteBuffer entryBuffer)
throws DatabaseException {
targetLogEntry.readEntry(entryBuffer, currentEntrySize,
currentEntryTypeVersion, true);
return true;
}
/**
* @return true if the last entry was an IN.
*/
public boolean isIN() {
return (targetCategory == IS_IN);
}
/**
* @return true if the last entry was a LN.
*/
public boolean isLN() {
return (targetCategory == IS_LN);
}
/**
* @return true if the last entry was a root
*/
public boolean isRoot() {
return (targetCategory == IS_ROOT);
}
/**
* Get the last LN seen by the reader.
*/
public LN getLN() {
return ((LNLogEntry) targetLogEntry).getLN();
}
/**
* Get the last entry seen by the reader as an IN.
*/
public IN getIN()
throws DatabaseException {
return ((INLogEntry) targetLogEntry).getIN(env);
}
/**
* Get the last databaseId seen by the reader.
*/
public DatabaseId getDatabaseId() {
if (targetCategory == IS_LN) {
return ((LNLogEntry) targetLogEntry).getDbId();
} else if (targetCategory == IS_IN) {
return ((INLogEntry) targetLogEntry).getDbId();
} else {
return null;
}
}
/**
* Get the last key seen by the reader.
*/
public byte[] getKey() {
return ((LNLogEntry) targetLogEntry).getKey();
}
/**
* Get the last key seen by the reader.
*/
public byte[] getDupTreeKey() {
return ((LNLogEntry) targetLogEntry).getDupKey();
}
private static class EntryInfo {
public LogEntry targetLogEntry;
public byte targetCategory;
EntryInfo(LogEntry targetLogEntry, byte targetCategory) {
this.targetLogEntry = targetLogEntry;
this.targetCategory = targetCategory;
}
}
}